#include<stdio.h>

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>

#include<alsa/asoundlib.h>

#include"wav.h"
#include"play_wav.h"

#include"alsa_mixer.h"

void mono2stereo(short *stereo_buf, const short *mono_buf, snd_pcm_sframes_t frames)
{
	int j = 0;
	int k = 0;
	//单声道转为立体声
	for (j = 0; j < frames; j++) {
		k = j * 2;
		stereo_buf[k] = stereo_buf[k + 1] = mono_buf[j];
	}
}

int play_audio_wav(char *file, int volume)
{
	int wav_fd = open(file, O_RDONLY);
	if (wav_fd < 0)
		printf("file open error\n");

	WAV_t wav;
	if (read_wav_head(wav_fd, &wav) < 0)
		printf("read wav head error\n");

	printf_wav_head_cn(wav);

	//play pcm
	int rc;
	snd_pcm_t *handle;
	snd_pcm_hw_params_t *params;
	snd_pcm_uframes_t frames;

	//设置PCM流向
	if ((rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0)
		printf("unable to open pcm device: %s\n", snd_strerror(rc));
	//分配硬件参数对象
	snd_pcm_hw_params_alloca(&params);
	//用默认值填写
	snd_pcm_hw_params_any(handle, params);
	//交错模式
	snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
	//将配置空间限制为仅包含一种格式
	switch (wav.fmt.BitsPerSample / 8) {
		case 1:
			//8位小端格式
			snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_U8);
			break;
		case 2:
			//16位小端格式
			snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
			break;
		case 3:
			//24位小端格式
			snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S24_LE);
			break;
	}
	//设置通道数
	snd_pcm_hw_params_set_channels(handle, params, wav.fmt.Channels);
	//设置采样率
	snd_pcm_hw_params_set_rate_near(handle, params, &wav.fmt.SampleRate, 0);
	//将参数写入驱动程序
	if ((rc = snd_pcm_hw_params(handle, params)) < 0)
		printf("unable to set hw parameters: %s\n", snd_strerror(rc));
	//使用足够大的缓冲区来保存一个周期
	snd_pcm_hw_params_get_period_size(params, &frames, 0);

	size_t mono_size = frames * wav.fmt.BitsPerSample / 8;
	int16_t *mono_buf = (int16_t *)calloc(mono_size, sizeof(int16_t));

	size_t stereo_size = 2 * mono_size;
	int16_t *stereo_buf = (int16_t *)calloc(stereo_size, sizeof(int16_t));

	spk_en(1);
	set_playback_volume(volume);
	for (;;) {
		if (1 == wav.fmt.Channels) {	
			//从文件读取音频数据
			rc = read(wav_fd, mono_buf, mono_size);
			if (rc < 0) {
				printf("end of file on input\n");
				break;
			} else if (rc != mono_size) {
				snd_pcm_drain(handle);
				printf("end of file\n");
				break;
			}
			mono2stereo(stereo_buf, mono_buf, frames);
		} else { //立体声
			rc = read(wav_fd, stereo_buf, stereo_size);
			if (rc < 0) {
				printf("end of file on input\n");
				break;
			} else if (rc != stereo_size) {
				snd_pcm_drain(handle);
				printf("end of file\n");
				break;
			}

		}

		//播放
		rc = snd_pcm_writei(handle, stereo_buf, frames);
		if (rc == -EPIPE) {
			printf("underrun\n");
			snd_pcm_drop(handle);
			break;
		} else if (rc < 0) {
			printf("error from writei:%s\n",snd_strerror(rc));
		}
	}
	snd_pcm_drain(handle);
	free(mono_buf);
	free(stereo_buf);
	close(wav_fd);
	spk_en(0);
	return 0;
}

